<?php
/**
 * Created by PhpStorm.
 * User: My
 * Date: 2018/11/27
 * Time: 12:04
 */

namespace App\Http\Helper;

use App\Exceptions\UserException;
use App\Services\DimensionAlgoHelper;
use UserRecordService;
use TestingItemService;
use TestingAlgoHelper;
use TestingDetailService;
use WechatUserService;

class RpcHelper
{

    /**
     * 修复用户答题记录
     * @param $orderId
     * @param $tid
     * @param $index
     * @param $answer
     * @param $weight
     * @return mixed
     * @throws UserException
     */
    public static function fixUserRecord($orderId, $tid, $index, $answer, $weight) {
        if (!in_array($tid, BusinessHelper::getDimensionChangeTids())) {
            throw new UserException('答题记录不能更改');
        }
        $userRecord = UserRecordService::getLastOneByOrderTid($orderId, $tid);
        if (!$userRecord) {
            throw new UserException('测评信息不存在');
        }
        if ($tid == BusinessHelper::getDimensionPayTid()) {
            $typeFourExpress = TestingItemService::typeFourItem($tid);
            $typeFourExpress = empty($typeFourExpress) ? null : $typeFourExpress;

            $answers = $userRecord['answers'];
            $answers = DataTransHelper::convertAnswer($answers);
            $isChange = false;
            foreach ($answers as &$val) {
                if ($val['index'] == $index) {
                    $val['weight'] = $weight;
                    $val['answer'] = $answer;
                    $isChange = true;
                }
            }
            if (!$isChange) {
                throw new UserException('题号异常');
            }
            $answers = DataTransHelper::arrToStr($answers);

            //计算测评的结果
            $result = TestingAlgoHelper::calculate($tid, $answers, $typeFourExpress);

            $data['id'] = $userRecord['id'];
            $data['score'] = $result['totalScore'];
            $data['answers'] = $answers;
            $data['final_answers'] = $result['finalAnswerStr'];
        } else {
            //计算测评的结果
            $dimensionAlgo = new DimensionAlgoHelper($tid);
            $answers = $userRecord['answers'];
            $answers = DataTransHelper::convertFourAnswer($answers);
            $isChange = false;

            foreach ($answers as &$val) {
                if ($val['id'] == $index) {
                    $val['value'] = $weight;
                    $val['weight'] = $weight;
                    $val['answer'] = $answer;
                    $isChange = true;
                }
            }
            if (!$isChange) {
                throw new UserException('题号异常');
            }
            $answers = DataTransHelper::arrFourToStr($answers);
            $result = $dimensionAlgo->calculate($answers);
            $data['id'] = $userRecord['id'];
            $data['score'] = $result['score'];
            $data['answers'] = $answers;
            $data['conclusion'] = $result['conclusion'];
            $data['final_answers'] = $dimensionAlgo->getAnswerStr();
        }

        return UserRecordService::update($data);
    }

    /**
     * 根据测评ID和订单ID获取标识信息
     * @param $tid
     * @param $orderId
     * @param $nutritionistId
     * @return array
     * @throws UserException
     */
    public static function getTestingBaseInfo($tid, $orderId, $nutritionistId) {
        $userRecord = UserRecordService::getLastOneByOrderIdTidNutriId($orderId, $tid, $nutritionistId);
        if (!$userRecord) {
            throw new UserException('用户不存在答题记录');
        }
        $dimensionAlgo = new DimensionAlgoHelper($tid);
        $dimensionAlgo->convertFinalAnswer($userRecord['final_answers']);
        $mark = $dimensionAlgo->getMarkInfo();

        //bmi的值
        $bmi = formatArrValue($mark, 'bmi', []);
        $bmiWeight = formatArrValue($bmi, 'weight');
        //月收入
        $monthlyIncome = formatArrValue($mark, 'monthly_income', []);
        $monthlyIncomeWeight = formatArrValue($monthlyIncome, 'weight');
        // 是否需要营养师关注
        $needFollow = formatArrValue($mark, 'need_follow', []);
        $needFollowWeight = formatArrValue($needFollow, 'weight');
        // 花费的费用
        $costFee = formatArrValue($mark, 'lose_weight_cost', []);
        $costFeeWeight = formatArrValue($costFee, 'weight');

        $systemGradeDesc = '';
        if ($bmiWeight == 'C') {
            $systemGradeDesc = '1D';
        } elseif ($bmiWeight == 'D') {
            $systemGradeDesc = '1C';
        } elseif ($bmiWeight == 'A' || $bmiWeight == 'B') {
            $systemGrade = [ 'A' => 0, 'B' => 0 ];
            //收入匹配等级
            if (in_array($monthlyIncomeWeight, ['C', 'D'])) {
                $systemGrade['A'] += 1;
            } else {
                $systemGrade['B'] += 1;
            }
            //bmi匹配的等级
            $systemGrade[$bmiWeight] += 1;
            // 是否需要关注匹配等级
            if (in_array($needFollowWeight, ['F'])) {
                $systemGrade['B'] += 1;
            } else {
                $systemGrade['A'] += 1;
            }
            // 减肥花费匹配等级
            if (in_array($costFeeWeight, ['C', 'D'])) {
                $systemGrade['A'] += 1;
            } else {
                $systemGrade['B'] += 1;
            }
            $A = $systemGrade['A'];
            $B = $systemGrade['B'];

            if ($B) {
                $systemGradeDesc = $B . 'B';
            }
            if ($A) {
                $systemGradeDesc = $systemGradeDesc ? "{$A}A+{$systemGradeDesc}" : "{$A}A";
            }
        } else {
            throw new UserException('bmi记录异常');
        }
        $breakfast = formatArrValue(formatArrValue($mark, 'breakfast', []), 'answer');
        $lunch = formatArrValue(formatArrValue($mark, 'lunch', []), 'answer');
        $dinner = formatArrValue(formatArrValue($mark, 'dinner', []), 'answer');

        return [
            'system_grade' => $systemGradeDesc,
            'system_info' => [
                'monthly_income' => formatArrValue($monthlyIncome, 'answer'),
                'bmi' => sprintf('%.2f', formatArrValue($bmi, 'answer')),
                'need_follow' => formatArrValue($needFollow, 'answer'),
                'cost_fee' => formatArrValue($costFee, 'answer'),
                'grade' => [
                    'monthly_income' => formatArrValue($monthlyIncome, 'weight'),
                    'bmi' => formatArrValue($bmi, 'weight'),
                    'need_follow' => formatArrValue($needFollow, 'weight'),
                    'cost_fee' => formatArrValue($costFee, 'weight'),
                ],
            ],
            'base_info' => [
                'sex' => formatArrValue(formatArrValue($mark, 'sex', []), 'answer'),
                'age' => formatArrValue(formatArrValue($mark, 'age', []), 'answer'),
                'height' => formatArrValue(formatArrValue($mark, 'height', []), 'answer'),
                'weight' => formatArrValue(formatArrValue($mark, 'weight', []), 'answer'),
                'origin' => formatArrValue(formatArrValue($mark, 'origin', []), 'answer'),
                'marital_status' => formatArrValue(formatArrValue($mark, 'marital_status', []), 'answer'),
                'family_children' => formatArrValue(formatArrValue($mark, 'family_children', []), 'answer'),
                'education' => formatArrValue(formatArrValue($mark, 'education', []), 'answer'),
                'occupation' => formatArrValue(formatArrValue($mark, 'occupation', []), 'answer'),
                'current_goal' => formatArrValue(formatArrValue($mark, 'current_goal', []), 'answer'),
            ],
            'special_info' => [
                'lose_weight_reason' => formatArrValue(formatArrValue($mark, 'lose_weight_reason', []), 'answer'),
                'current_time' => formatArrValue(formatArrValue($mark, 'current_time', []), 'answer'),
                'except_item' => formatArrValue(formatArrValue($mark, 'except_item', []), 'answer'),
                'purchase_ingredients' => formatArrValue(formatArrValue($mark, 'purchase_ingredients', []), 'answer'),
                'social_activities' => formatArrValue(formatArrValue($mark, 'social_activities', []), 'answer'),
                'three_meals' => [ 'breakfast' => $breakfast, 'lunch' => $lunch, 'dinner' => $dinner ],
                'family_support' => formatArrValue(formatArrValue($mark, 'family_support', []), 'answer'),
                'budget' => formatArrValue(formatArrValue($mark, 'budget', []), 'answer'),
                'exercise_frequency' => formatArrValue(formatArrValue($mark, 'exercise_frequency', []), 'answer'),
                'lose_weight_ways' => formatArrValue(formatArrValue($mark, 'lose_weight_ways', []), 'answer'),
                'knowledge_sources' => formatArrValue(formatArrValue($mark, 'knowledge_sources', []), 'answer'),
            ]
        ];
    }

    /**
     * 获取订单的测评信息
     * @param $tid
     * @param $orderId
     * @param $nutritionistId
     * @return array
     * @throws UserException
     */
    public static function getUserTestingInfo($tid, $orderId, $nutritionistId) {
        $testingDetail = TestingDetailService::getById($tid);
        $userRecord = UserRecordService::getLastOneByOrderIdTidNutriId($orderId, $tid, $nutritionistId);
        if (!$userRecord) {
            throw new UserException('用户不存在答题记录');
        }
        $dimensionAlgo = new DimensionAlgoHelper($tid);
        $finalAnswer = $dimensionAlgo->convertFinalAnswer($userRecord['final_answers']);
        $mark = $dimensionAlgo->getMarkInfo();
        $questionList = $dimensionAlgo->getQuestion();

        $bmi = sprintf('%.2f', formatArrValue(formatArrValue($mark, 'bmi', []), 'answer'));
        $age = formatArrValue(formatArrValue($mark, 'age', []), 'answer');
        $sex = formatArrValue(formatArrValue($mark, 'sex', []), 'answer');
        $height = formatArrValue(formatArrValue($mark, 'height', []), 'answer');
        $weight = formatArrValue(formatArrValue($mark, 'weight', []), 'answer');
        $currentGoal = formatArrValue(formatArrValue($mark, 'current_goal', []), 'answer');
        $exceptItem = formatArrValue(formatArrValue($mark, 'except_item', []), 'answer');

        $testingInfo = [];
        $index = 1;
        foreach ($questionList as $question) {
            array_push($testingInfo, [
                'index' => $index++,
                'title' => $question['title'],
                'answer' => formatArrValue($finalAnswer[$question['id']], 'answer', '')
            ]);
        }

        $record = "性别：{$sex} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 年龄：{$age} <br>BMI：{$bmi}  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  身高：{$height}   &nbsp;(cm)    体重： {$weight} &nbsp; (kg)  <br>减重目标：{$currentGoal} <br>异常项：{$exceptItem}";

        return [
            'testing_name' => $testingDetail['name'],
            'record' => $record,
            'testing_info' => $testingInfo,
            'middle' => self::getMiddleValue($mark)
        ];
    }

    /**
     * 获取测评订单的 PD 值
     * @param $tid
     * @param $orderId
     * @param $nutritionistId
     * @return array
     * @throws UserException
     */
    public static function getOrderPDInfo($tid, $orderId, $nutritionistId) {
        $userRecord = UserRecordService::getLastOneByOrderIdTidNutriId($orderId, $tid, $nutritionistId);
        if (!$userRecord) {
            throw new UserException('用户不存在答题记录');
        }
        $dimensionAlgo = new DimensionAlgoHelper($tid);
        $mark = $dimensionAlgo->getMarkInfo();

        $exerciseFrequencyWeight = formatArrValue(formatArrValue($mark, 'exercise_frequency', []), 'weight');
        $breakfastWeight = formatArrValue(formatArrValue($mark, 'breakfast', []), 'weight');
        $lunchWeight = formatArrValue(formatArrValue($mark, 'lunch', []), 'weight');
        $dinnerWeight = formatArrValue(formatArrValue($mark, 'dinner', []), 'weight');

        $P = in_array($exerciseFrequencyWeight, ['A', 'B']) ? 1 : ($exerciseFrequencyWeight == 'C' ? 2 : 3);

        $ab = $c = $d = 0;
        in_array($breakfastWeight, ['A', 'B']) ? $ab++ : ($breakfastWeight == 'C' ? $c++ : $d++);
        in_array($lunchWeight, ['A', 'B']) ? $ab++ : ($lunchWeight == 'C' ? $c++ : $d++);
        in_array($dinnerWeight, ['A', 'B']) ? $ab++ : ($dinnerWeight == 'C' ? $c++ : $d++);

        $D = $ab / 3 > 0.35 ? 1 : ($c / 3 > 0.35 ? 2 : ($d / 3 > 0.35 ? 3 : 3));

        return [
            'p' => $P,
            'd' => $D,
        ];
    }

    /**
     * 计算中间值
     * @param $markInfo
     * @return string
     */
    private static function getMiddleValue($markInfo) {
        $data = [];
        $height = formatArrValue(formatArrValue($markInfo, 'height', []), 'answer');
        $weight = formatArrValue(formatArrValue($markInfo, 'weight', []), 'answer');
        $currentGoal = formatArrValue(formatArrValue($markInfo, 'current_goal', []), 'answer');
        $bmi = formatArrValue(formatArrValue($markInfo, 'bmi', []), 'answer');

        $breakfast = formatArrValue(formatArrValue($markInfo, 'breakfast', []), 'answer');
        $lunch = formatArrValue(formatArrValue($markInfo, 'lunch', []), 'answer');
        $dinner = formatArrValue(formatArrValue($markInfo, 'dinner', []), 'answer');
        $exerciseFrequencyWeight = formatArrValue(formatArrValue($markInfo, 'exercise_frequency', []), 'weight');

        $breakfastWeight = formatArrValue(formatArrValue($markInfo, 'breakfast', []), 'weight');
        $lunchWeight = formatArrValue(formatArrValue($markInfo, 'lunch', []), 'weight');
        $dinnerWeight = formatArrValue(formatArrValue($markInfo, 'dinner', []), 'weight');

        //i（最低健康体重）=18.5*题目22身高（m）的平方
        $i = 18.5 * $height * $height / 10000;
        $str = "最低健康体重:" . number_format($i, 2) . "Kg";

        //q（目标体重）=题目23体重（kg）-题目36减重目标
        $q = $weight - $currentGoal;
        $str .= " &nbsp;&nbsp;&nbsp;&nbsp; 目标体重:" . $q . "Kg";

        //s（建议减重目标）=题目23体重（kg）-i
        $s = $weight - $i;
        $str .= " <br>建议不大于减重目标:" . number_format($s, 2) . "Kg";

        //E（每日所需热量）=（身高-1.05）*100*L
        $L = $bmi < 18.5 ? rand(35, 40) : rand(25, 30);
        $E = ($height - 105) * $L;
        $str .= " &nbsp;&nbsp;&nbsp;&nbsp; 每日所需热量:" . $E . "   卡路里";

        //E2（每日膳食热量）=K卡路里亏空系数*E（每日所需热量）
        if ($currentGoal <= 4)
            $K = 0.9;
        elseif ($currentGoal > 4 && $currentGoal <= 7)
            $K = 0.85;
        elseif ($currentGoal > 7 && $currentGoal <= 10)
            $K = 0.8;
        elseif ($currentGoal > 10 && $currentGoal <= 13)
            $K = 0.75;
        else
            $K = 0.7;
        $E2 = $K * $E;
        $str .= " &nbsp;&nbsp;&nbsp;&nbsp; 每日膳食热量:" . $E2 . "  卡路里";

        $str .= " <br> 三餐：" . "<br> &nbsp;&nbsp;&nbsp;&nbsp; 早餐：{$breakfast}" . "<br> &nbsp;&nbsp;&nbsp;&nbsp; 午餐：{$lunch}" . "<br> &nbsp;&nbsp;&nbsp;&nbsp; 晚餐：{$dinner}";

        //P（运动）===第8题
        $str .= " <br> " . (in_array($exerciseFrequencyWeight, ['A', 'B']) ? 'P:1' : ($exerciseFrequencyWeight == 'C' ? 'P:2' : 'P:3'));

        $ab = $c = $d = 0;
        in_array($breakfastWeight, ['A', 'B']) ? $ab++ : ($breakfastWeight == 'C' ? $c++ : $d++);
        in_array($lunchWeight, ['A', 'B']) ? $ab++ : ($lunchWeight == 'C' ? $c++ : $d++);
        in_array($dinnerWeight, ['A', 'B']) ? $ab++ : ($dinnerWeight == 'C' ? $c++ : $d++);

        $str .= " <br> " . ($ab / 3 > 0.35 ? 'D:1' : ($c / 3 > 0.35 ? 'D:2' : ($d / 3 > 0.35 ? 'D:3' : 'D:3')));

        return  $str;
    }

    public static function syncVirtualOrderRecordInfo($businessData)
    {
        return UserRecordService::update($businessData);
    }

    /**
     * 获取五维测评列表
     * @return mixed
     */
    public static function getFiveDimensionQnList()
    {
        return TestingDetailService::getFiveDimesionList();
    }

    /**
     * @param $tid
     * @param $phone
     * @return array
     * @throws UserException
     */
    public static function getPhysiqueResultByPhone($tid, $phone) {
        $user = WechatUserService::getByPhone($phone);
        if (!$user) {
            throw new UserException('未查询到用户信息');
        }
        return ResultHelper::dimensionResult('blackPhysiqueResult', $user['uid'], $tid);
    }
}